#pragma once
#include "thread.h"
#include <string>

namespace krryn{
namespace core{
	template<typename _Ty> 
	class refc_ptr;

	class job{
	public:
		virtual std::string get_name();
		virtual void execute() = 0;
		virtual void done() {};
		virtual ~job() {}
	};

	class wait_job : public job{
	public:
		wait_job(event &a_Event) : m_Event(a_Event) {}

		virtual void execute() = 0;

		virtual void done(){
			m_Event.trigger();
		}
	private:
		event &m_Event;
	};

	class job_manager;
	class job_group{
	public:
		job_group(const std::string &a_Name);
		~job_group();

		void add(job* a_Job);
		void add_to(job_manager &a_Manager);

		void depends_on_all_of(job_group* a_Group);
		void depends_on_any_of(size_t a_Amount, job_group* a_Group);
	private:
		class group_job;
		class impl;
		impl *m_Pimpl;
		const std::string m_Name;
	};

	class job_thread : public thread{
	public:
		typedef unsigned long thread_id_t;

		explicit job_thread(job_manager &a_Manager);
		virtual ~job_thread();
		virtual void run();
	private:
		class impl;
		impl *m_Pimpl;
	};

	class job_manager{
	public:
		explicit job_manager(size_t a_NumberOfThreads);

		~job_manager();

		void add_group(job_group* a_Group);
		void add_job(job* a_Job);

		long get_number_of_threads() const;
		job* next();
	private:
		class impl;
		impl *m_Pimpl;
	};
}
}